package com.jdj.framework.dao.mybatis.provider;

import static org.apache.ibatis.jdbc.SqlBuilder.BEGIN;
import static org.apache.ibatis.jdbc.SqlBuilder.DELETE_FROM;
import static org.apache.ibatis.jdbc.SqlBuilder.FROM;
import static org.apache.ibatis.jdbc.SqlBuilder.INSERT_INTO;
import static org.apache.ibatis.jdbc.SqlBuilder.SELECT;
import static org.apache.ibatis.jdbc.SqlBuilder.SET;
import static org.apache.ibatis.jdbc.SqlBuilder.SQL;
import static org.apache.ibatis.jdbc.SqlBuilder.UPDATE;
import static org.apache.ibatis.jdbc.SqlBuilder.VALUES;
import static org.apache.ibatis.jdbc.SqlBuilder.WHERE;

import com.jdj.framework.core.base.utils.StringUtils;
import com.jdj.framework.dao.mybatis.entity.BaseEntity;
import com.jdj.framework.dao.mybatis.entity.EntityPropertyDescriptor;
import com.jdj.framework.dao.mybatis.provider.impl.InsertSqlProviderImpl;
import com.jdj.framework.dao.mybatis.provider.impl.UpdateSqlProviderImpl;
import com.jdj.framework.dao.mybatis.utils.EntityUtil;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

/**
 * 基础Mapper
 * @author caijinbang
 * @date 2019-04-14 13:16
 */
public class BaseMapperProvider {
    private static final Logger logger = LoggerFactory.getLogger(BaseMapperProvider.class);

    private InsertSqlProvider insertSqlProvider = new InsertSqlProviderImpl();

    private UpdateSqlProvider updateSqlProvider = new UpdateSqlProviderImpl();

    @Qualifier(value = "insertSqlProvider")
    @Autowired(required = false)
    public void setInsertSqlProvider(InsertSqlProvider insertSqlProvider) {
        this.insertSqlProvider = insertSqlProvider;
    }

    @Qualifier(value = "updateSqlProvider")
    @Autowired(required = false)
    public void setUpdateSqlProvider(UpdateSqlProvider updateSqlProvider) {
        this.updateSqlProvider = updateSqlProvider;
    }


    /**
     * 根据主键查询
     *
     * @param param
     * @return
     */
    @SuppressWarnings("unchecked")
    public <Entity extends BaseEntity> String selectByPrimaryKey(Map<String, Object> param) {
        Class<Entity> entityClass = (Class<Entity>) param.get("entityClass");
        BEGIN();
        SELECT("*");
        FROM(EntityUtil.getTableName(entityClass));
        try {
            WHERE(EntityUtil.getPrimaryKeyColumnName(entityClass) + "=#{primaryKey,jdbcType=VARCHAR}");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return SQL();
    }

    /**
     * 根据主键删除
     *
     * @param param
     * @return
     */
    @SuppressWarnings("unchecked")
    public <Entity extends BaseEntity> String deleteByPrimaryKey(Map<String, Object> param) {
        Class<Entity> entityClass = (Class<Entity>) param.get("entityClass");
        BEGIN();
        DELETE_FROM(EntityUtil.getTableName(entityClass));
        try {
            WHERE(EntityUtil.getPrimaryKeyColumnName(entityClass) + "=#{primaryKey,jdbcType=VARCHAR}");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return SQL();
    }

    /**
     * 根据主键修改有值字段
     *
     * @param entity
     * @return
     */
    public <Entity extends BaseEntity> String updateByPrimaryKeySelective(Entity entity) {
        List<EntityPropertyDescriptor> entityPropertyDescriptors = EntityUtil.getEntityPropertyDescriptor(entity
            .getClass());
        // 主键字段
        EntityPropertyDescriptor primaryKeyPropertyDescriptor = EntityUtil.getPropertyDescriptorByFieldName(
            entity.getClass(), EntityUtil.getPrimaryKeyFieldName(entity.getClass()));
        // 版本字段
        EntityPropertyDescriptor versionPropertyDescriptor = EntityUtil.getPropertyDescriptorByFieldName(
            entity.getClass(), EntityUtil.getVersionFileName(entity.getClass()));
        BEGIN();
        UPDATE(EntityUtil.getTableName(entity.getClass()));
        // 组装update set 的设值部分
        StringBuffer setSql = new StringBuffer();
        String comma = "";
        for (Iterator<EntityPropertyDescriptor> iterator = entityPropertyDescriptors.iterator(); iterator.hasNext(); ) {
            EntityPropertyDescriptor currentModelPropertyDescriptor = iterator.next();
            // 排除ID、版本号、不包含在update set部分
            if (currentModelPropertyDescriptor.getFieldName() == null) {
                continue;
            }
            if (currentModelPropertyDescriptor.getFieldName().equals(primaryKeyPropertyDescriptor.getFieldName())) {
                continue;
            }
            if (versionPropertyDescriptor != null
                && currentModelPropertyDescriptor.getFieldName().equals(versionPropertyDescriptor.getFieldName())) {
                continue;
            }
            // update set 只包含被修改的字段
            if (entity.obtainSettedFields().contains(currentModelPropertyDescriptor.getFieldName())
                && currentModelPropertyDescriptor.getColumnName() != null) {
                //第二个开始的set字段后，都添加逗号
                setSql.append(comma);
                setSql.append(currentModelPropertyDescriptor.getColumnName());
                setSql.append("=#{");
                setSql.append(currentModelPropertyDescriptor.getFieldName());
                setSql.append('}');
                comma = ",";
            }
        }
        //有版本号字段 自动加1
        if (entity.obtainSettedFields().size() > 0 && versionPropertyDescriptor != null) {
            setSql.append(',');
            setSql.append(versionPropertyDescriptor.getColumnName());
            setSql.append("=(#{");
            setSql.append(versionPropertyDescriptor.getFieldName());
            setSql.append("}+1)");
        }
        //其它set sql
        if (entity.obtainSettedFields().size() > 0) {
            updateSqlProvider.appendSetSql(setSql, entity);
        }
        //
        SET(setSql.toString());
        // 组装where部分
        StringBuffer whereSql = new StringBuffer();
        whereSql.append(primaryKeyPropertyDescriptor.getColumnName());
        whereSql.append("=#{");
        whereSql.append(primaryKeyPropertyDescriptor.getFieldName());
        whereSql.append("}");
        // 版本号作为条件
        if (versionPropertyDescriptor != null) {
            whereSql.append(" and ");
            whereSql.append(versionPropertyDescriptor.getColumnName());
            whereSql.append("=#{");
            whereSql.append(versionPropertyDescriptor.getFieldName());
            whereSql.append("}");
        }
        WHERE(whereSql.toString());
        return SQL();
    }

    /**
     * 根据主键修改(非空字符/非null)字段
     *
     * @param entity
     * @return
     */
    public <Entity extends BaseEntity> String updateNotEmptyByPrimaryKey(Entity entity) {
        List<EntityPropertyDescriptor> entityPropertyDescriptors = EntityUtil.getEntityPropertyDescriptor(entity
            .getClass());
        // 主键字段
        EntityPropertyDescriptor primaryKeyPropertyDescriptor = EntityUtil.getPropertyDescriptorByFieldName(
            entity.getClass(), EntityUtil.getPrimaryKeyFieldName(entity.getClass()));
        // 版本字段
        EntityPropertyDescriptor versionPropertyDescriptor = EntityUtil.getPropertyDescriptorByFieldName(
            entity.getClass(), EntityUtil.getVersionFileName(entity.getClass()));
        BEGIN();
        UPDATE(EntityUtil.getTableName(entity.getClass()));
        // 组装update set 的设值部分
        StringBuffer setSql = new StringBuffer();
        String comma = "";
        for (Iterator<EntityPropertyDescriptor> iterator = entityPropertyDescriptors.iterator(); iterator.hasNext(); ) {
            EntityPropertyDescriptor currentModelPropertyDescriptor = iterator.next();
            Serializable currentModelPropertyValue;
            // 排除ID、版本号、不包含在update set部分
            if (currentModelPropertyDescriptor.getFieldName() == null) {
                continue;
            }
            if (currentModelPropertyDescriptor.getFieldName().equals(primaryKeyPropertyDescriptor.getFieldName())) {
                continue;
            }
            if (versionPropertyDescriptor != null
                && currentModelPropertyDescriptor.getFieldName().equals(versionPropertyDescriptor.getFieldName())) {
                continue;
            }
            currentModelPropertyValue = EntityUtil.getFieldValueByFieldName(entity, currentModelPropertyDescriptor.getFieldName());
            // update set 只(非空字符/非null)的字段
            if (currentModelPropertyDescriptor.getColumnName() != null &&
                currentModelPropertyValue != null &&
                currentModelPropertyValue.toString().length() > 0) {
                //第二个开始的set字段后，都添加逗号
                setSql.append(comma);
                setSql.append(currentModelPropertyDescriptor.getColumnName());
                setSql.append("=#{");
                setSql.append(currentModelPropertyDescriptor.getFieldName());
                setSql.append('}');
                comma = ",";
            }

        }
        //有版本号字段 自动加1
        if (entity.obtainSettedFields().size() > 0 && versionPropertyDescriptor != null) {
            setSql.append(',');
            setSql.append(versionPropertyDescriptor.getColumnName());
            setSql.append("=(#{");
            setSql.append(versionPropertyDescriptor.getFieldName());
            setSql.append("}+1)");
        }
        //其它set sql
        if (entity.obtainSettedFields().size() > 0) {
            updateSqlProvider.appendSetSql(setSql, entity);
        }
        //
        SET(setSql.toString());
        // 组装where部分
        StringBuffer whereSql = new StringBuffer();
        whereSql.append(primaryKeyPropertyDescriptor.getColumnName());
        whereSql.append("=#{");
        whereSql.append(primaryKeyPropertyDescriptor.getFieldName());
        whereSql.append("}");
        // 版本号作为条件
        if (versionPropertyDescriptor != null) {
            whereSql.append(" and ");
            whereSql.append(versionPropertyDescriptor.getColumnName());
            whereSql.append("=#{");
            whereSql.append(versionPropertyDescriptor.getFieldName());
            whereSql.append("}");
        }
        WHERE(whereSql.toString());
        return SQL();
    }

    /**
     * 根据主键修改(非null)字段
     *
     * @param entity
     * @return
     */
    public <Entity extends BaseEntity> String updateNotNullByPrimaryKey(Entity entity) {
        List<EntityPropertyDescriptor> entityPropertyDescriptors = EntityUtil.getEntityPropertyDescriptor(entity
            .getClass());
        // 主键字段
        EntityPropertyDescriptor primaryKeyPropertyDescriptor = EntityUtil.getPropertyDescriptorByFieldName(
            entity.getClass(), EntityUtil.getPrimaryKeyFieldName(entity.getClass()));
        // 版本字段
        EntityPropertyDescriptor versionPropertyDescriptor = EntityUtil.getPropertyDescriptorByFieldName(
            entity.getClass(), EntityUtil.getVersionFileName(entity.getClass()));
        BEGIN();
        UPDATE(EntityUtil.getTableName(entity.getClass()));
        // 组装update set 的设值部分
        StringBuffer setSql = new StringBuffer();
        String comma = "";
        for (Iterator<EntityPropertyDescriptor> iterator = entityPropertyDescriptors.iterator(); iterator.hasNext(); ) {
            EntityPropertyDescriptor currentModelPropertyDescriptor = iterator.next();
            Serializable currentModelPropertyValue;
            // 排除ID、版本号、不包含在update set部分
            if (currentModelPropertyDescriptor.getFieldName() == null) {
                continue;
            }
            if (currentModelPropertyDescriptor.getFieldName().equals(primaryKeyPropertyDescriptor.getFieldName())) {
                continue;
            }
            if (versionPropertyDescriptor != null
                && currentModelPropertyDescriptor.getFieldName().equals(versionPropertyDescriptor.getFieldName())) {
                continue;
            }
            currentModelPropertyValue = EntityUtil.getFieldValueByFieldName(entity, currentModelPropertyDescriptor.getFieldName());
            // update set 只(非null)的字段
            if (currentModelPropertyDescriptor.getColumnName() != null &&
                currentModelPropertyValue != null) {
                //第二个开始的set字段后，都添加逗号
                setSql.append(comma);
                setSql.append(currentModelPropertyDescriptor.getColumnName());
                setSql.append("=#{");
                setSql.append(currentModelPropertyDescriptor.getFieldName());
                setSql.append('}');
                comma = ",";
            }

        }
        //有版本号字段 自动加1
        if (entity.obtainSettedFields().size() > 0 && versionPropertyDescriptor != null) {
            setSql.append(',');
            setSql.append(versionPropertyDescriptor.getColumnName());
            setSql.append("=(#{");
            setSql.append(versionPropertyDescriptor.getFieldName());
            setSql.append("}+1)");
        }
        //其它set sql
        if (entity.obtainSettedFields().size() > 0) {
            updateSqlProvider.appendSetSql(setSql, entity);
        }
        //
        SET(setSql.toString());
        // 组装where部分
        StringBuffer whereSql = new StringBuffer();
        whereSql.append(primaryKeyPropertyDescriptor.getColumnName());
        whereSql.append("=#{");
        whereSql.append(primaryKeyPropertyDescriptor.getFieldName());
        whereSql.append("}");
        // 版本号作为条件
        if (versionPropertyDescriptor != null) {
            whereSql.append(" and ");
            whereSql.append(versionPropertyDescriptor.getColumnName());
            whereSql.append("=#{");
            whereSql.append(versionPropertyDescriptor.getFieldName());
            whereSql.append("}");
        }
        WHERE(whereSql.toString());
        return SQL();
    }

    /**
     * 插入有值字段
     *
     * @param entity
     * @return
     */
    public <Entity extends BaseEntity> String insertSelective(Entity entity) {
        BEGIN();
        INSERT_INTO(EntityUtil.getTableName(entity.getClass()));
        StringBuffer nameSqlSB = new StringBuffer();
        StringBuffer valueSqlSB = new StringBuffer();
        String comma = "";
        //如果版本号是null,被排除。则默认值为1，在insertSqlProvider里实现
        if (EntityUtil.getVersionValue(entity) == null) {
            entity.obtainSettedFields().remove(EntityUtil.getVersionFileName(entity.getClass()));
        }
        //取到所有列名
        for (EntityPropertyDescriptor entityPropertyDescriptor : EntityUtil.getEntityPropertyDescriptor(entity
            .getClass())) {
            String fieldName = entityPropertyDescriptor.getFieldName();
            Serializable fieldValue = EntityUtil.getFieldValueByFieldName(entity, fieldName);
            String columnName = entityPropertyDescriptor.getColumnName();
            //只追加有值实体字段
            if (!StringUtils.isEmpty(fieldName) && !StringUtils.isEmpty(columnName) && fieldValue != null) {
                nameSqlSB.append(comma);
                valueSqlSB.append(comma);
                nameSqlSB.append(columnName);
                valueSqlSB.append("#{");
                valueSqlSB.append(fieldName);
                valueSqlSB.append("}");
                comma = ",";
            }
        }
        //其它默认拼接的Sql
        if (entity.obtainSettedFields().size() > 0) {
            insertSqlProvider.appendNameSqlAndValueSql(nameSqlSB, valueSqlSB, entity);
        }
        //
        VALUES(nameSqlSB.toString(), valueSqlSB.toString());
        return SQL();
    }
}
